#parses TeaTime decrypted mdl file

import os, sys
from Sanae3D.lib.ModelObject import Model3D
from Sanae3D.lib.StructReader import StructReader

class TeaTime_mdl(Model3D):
    
    header = "3D_MODEL_FILE"
    key = [0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7]
    
    def __init__(self, obj3D=None, inFile=None, outFile=None):
        
        super(TeaTime_mdl, self).__init__("Love_Death_MDL")
        self.inFile = inFile
        self.outFile = outFile
        self.encrypted = False
        self.mdlFormat = 0
    
    def check_encryption(self):
        
        temp = self.inFile.readline().strip()
        if temp != self.header:
            self.encrypted = True
            
    def check_format(self):
        '''HCT format does not encrypt spaces. This check may be unnecessary
        if we can guarantee that older formats will never have the space
        character in their encrypted file'''
        
        curPos = self.inFile.tell()
        temp = self.inFile.read_byte(60)
        self.inFile.seek(curPos)
        
        if 0x20 in temp:
            self.mdlFormat = 1
            
    def decrypt_string(self, string):
    
        new_str = []
        #if self.mdlFormat == 1:
        for i in range(len(string)):
            if ord(string[i]) in [0x09, 0x20]:
                new_str.append(string[i])
            else:
                new_str.append(chr(ord(string[i]) ^ self.key[i % len(self.key)]))
        #else:
            #for i in range(len(string)):
                #new_str.append(chr(ord(string[i]) ^ self.key[i % len(self.key)]))
        return ''.join(new_str)
        
    def read_line(self):
        
        line = self.inFile.readline()
        if self.encrypted:
            line = self.decrypt_string(line.strip())
        return line.strip()
    
    def parse_materials(self):
        
        numMat = int(self.read_line().strip())
        for i in range(numMat):

            matName = self.read_line()[5:]
            diffuse = self.read_line()[8:].split()
            ambient = self.read_line()[8:].split()
            specular = self.read_line()[9:].split()
            power = self.read_line()[6:]
            textureFlag = self.read_line()[12:]
            texName = self.read_line()[12:]
            line = self.read_line() #check value for HCT
            if line:
                line = self.read_line()
            self.create_material(i)
            self.add_material_name(i, matName)
            self.add_specular(i, specular)
            self.add_diffuse(i, diffuse)
            self.add_ambient(i, ambient)
            self.add_power(i, power)
            self.add_texture_name(i, texName)

    def parse_vertices(self, meshName):
    
        numVerts = int(self.read_line())
        for i in range(numVerts):
            vx, vy, vz = self.read_line()[4:].split()
            nx, ny, nz = self.read_line()[7:].split()
            tu, tv = self.read_line()[3:].split()
            bones = self.read_line()[9:].split()
            weights = self.read_line()[11:].split()
            self.read_line()
            
            self.create_vertex(meshName, i)
            self.add_coords(meshName, i, [vx, vy, vz])
            self.add_vert_normals(meshName, i, [nx, ny, nz])
            self.add_vert_uv(meshName, i, [tu ,tv])
        
    def parse_faces(self, meshName):
        
        totalFaces = int(self.read_line()[11:])
        totalSect = int(self.read_line()[9:])
        faceNum = 0
        for i in range(totalSect):
            matNum = int(self.read_line()[11:])
            numFaces = int(self.read_line()[8:])
            for i in range(numFaces):
                v1, v2, v3 = self.read_line().split()
                self.create_face(meshName, faceNum)
                self.add_face_verts(meshName, faceNum, [v1, v2, v3])
                self.add_face_material(meshName, faceNum, matNum)
                faceNum += 1
            #empty line
            self.read_line()
            
    def parse_mdl(self):
        
        self.check_encryption()
        #self.check_format()
        self.inFile.readline()
        
        meshName = "obj"
        self.create_object(meshName)
        
        #material section
        section = self.read_line()
        self.parse_materials()
        
        #vertex section
        section = self.read_line()
        self.parse_vertices(meshName)
        
        #faces section
        section = self.read_line()
        self.parse_faces(meshName)
        
        #shader section?
        section = self.read_line()
        
def read_file(path):
    
    openFile = StructReader(open(path,'rb'))
    mdlObj = TeaTime_mdl(inFile=openFile)
    mdlObj.parse_mdl()
    return mdlObj

def definitions():
    
    return ["3D_MODEL", "\xCC\xBA\xA2\xB1\xB4\xBE\xBC\xB4"], "MDL", "TeaTime mdl", ""
